package com.bumptech.glide.load.engine

import com.bumptech.glide.load.Key
import com.bumptech.glide.load.engine.cache.DiskCache
import com.gitee.wsl.common.more.ext.glide.cache.DiskLruPartitionCacheFactory.Companion.DISK_LRU_PARTITION_CACHE
import com.gitee.wsl.common.more.ext.glide.cache.DiskLruPartitionCacheFactory.Companion.DISK_LRU_PARTITION_DOWNLOAD
import com.gitee.wsl.common.more.ext.glide.cache.DiskLruPartitionCacheFactory.Companion.DISK_LRU_PARTITION_DOWNLOAD_PICTURE
import com.gitee.wsl.common.more.ext.glide.ext.OriginalKey
import com.gitee.wsl.common.more.ext.glide.ext.PartitionSignature
import okio.appendingSink
import okio.buffer
import okio.source
import timber.log.Timber
import java.io.File


class DiskLruPartitionMapCacheWrapper(private val baseDiskCache: DiskCache) : DiskCache {

    private val diskCacheMap = mutableMapOf<String,DiskCache>()

    fun addDiskCache(partitionCacheName:String,diskCache: DiskCache){
        diskCacheMap[partitionCacheName]=diskCache
    }

    override fun get(key: Key): File? {
        var file=baseDiskCache.get(key)
        if(file == null && key is DataCacheKey){
            diskCacheMap.forEach{
                file=it.value.get(key)
                file?.let{
                    return@forEach
                }
            }
        }
        Timber.d("get key:$key")
        return file
    }

    override fun put(key: Key, writer: DiskCache.Writer) {
        Timber.d("put key:$key")
        if(key is DataCacheKey){
            when(key){
                DataCacheKey(key.sourceKey, PartitionSignature.DOWNLOAD_PICTURE)->{
                    put(DISK_LRU_PARTITION_DOWNLOAD_PICTURE,key, writer)
                    return
                }
                DataCacheKey(key.sourceKey, PartitionSignature.DOWNLOAD)->{
                    put(DISK_LRU_PARTITION_DOWNLOAD,key, writer)
                    return
                }
                else->{}
            }
        }
        baseDiskCache.put(key, writer)

    }

    override fun delete(key: Key) {
        if(key is DataCacheKey){
            when(key){
                DataCacheKey(key.sourceKey, PartitionSignature.DOWNLOAD_PICTURE)->{
                    delete(DISK_LRU_PARTITION_DOWNLOAD_PICTURE,key)
                    return
                }
                DataCacheKey(key.sourceKey, PartitionSignature.DOWNLOAD)->{
                    delete(DISK_LRU_PARTITION_DOWNLOAD,key)
                    return
                }
                else->{}
            }
        }
        baseDiskCache.delete(key)
        Timber.d("delete key:$key")
    }
    override fun clear() {
        baseDiskCache.clear()
        Timber.d("clear")
    }

    fun get(partition:String,key: Key): File? {
        Timber.d("get key:$key from partition:$partition")
        return diskCacheMap[partition]?.get(key)
    }

    fun put(partition:String,key: Key, writer: DiskCache.Writer) {
        Timber.d("put key:$key to partition:$partition")
        diskCacheMap[partition]?.put(key, writer)
    }

    fun delete(partition:String,key: Key) {
        Timber.d("delete key:$key from partition:$partition")
        diskCacheMap[partition]?.delete(key)
    }

    fun clear(partition:String){
        Timber.d("clear partition:$partition")
        diskCacheMap[partition]?.clear()
    }

    fun move(partition:String,url: String,toPartition:String){
        move(partition, OriginalKey(url), toPartition)
    }

    fun move(url: String,toPartition:String){
        move(DISK_LRU_PARTITION_CACHE, OriginalKey(url), toPartition)
    }

    fun move(partition:String,key: Key,toPartition:String){
       if(partition == toPartition) return
       val fromCache = if(partition == DISK_LRU_PARTITION_CACHE) baseDiskCache else diskCacheMap[partition]
       val toCache  = if( toPartition == DISK_LRU_PARTITION_CACHE) baseDiskCache else diskCacheMap[toPartition]
       val file = fromCache?.get(key)?:return
       val toFile = toCache?.get(key)
       toFile?.let { return }
       toCache?.put(key,CacheFileMoveWriter(file))
       fromCache.delete(key)
    }

    fun copy(partition:String,url: String,toPartition:String){
        copy(partition, OriginalKey(url), toPartition)
    }

    fun copy(partition:String,key: Key,toPartition:String){
        if(partition == toPartition) return
    }
}

class CacheFileMoveWriter(val src:File): DiskCache.Writer{
    override fun write(file: File): Boolean {
        val inBuffer = file.source()
        val srcBuffer = src.appendingSink()
        inBuffer.buffer().readAll(srcBuffer)
        inBuffer.close()
        srcBuffer.close()
        return true
    }
}